/*
 * Copyright 2008 Andrej Herich
 * 
 * http://azetclient.yw.sk/
 * http://azetclient.googlecode.com/
 * 
 * This file is part of AzetClient.
 * 
 * AzetClient is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * AzetClient is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with AzetClient.  If not, see <http://www.gnu.org/licenses/>.
 */

package sk.yw.azetclient.azet;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.log4j.Logger;
import sk.yw.azetclient.HtmlEntitiesConverter;
import sk.yw.azetclient.Main;
import sk.yw.azetclient.connection.AbstractParser;
import sk.yw.azetclient.connection.PagesSaver;
import sk.yw.azetclient.model.Buddy;

/**
 *
 * @author error216
 */
public class BuddyListParser extends AbstractParser<List<Buddy>> {
    
    private static final Logger logger = Logger.getLogger(BuddyListParser.class);
    
    private static final String BUDDY_BEGIN =
            "<input type=\"checkbox\" name=\"kere[]\"";
    private static final Pattern BUDDY_NAME = Pattern.compile(
            "<a href=\"http://moje\\.azet\\.sk/posta\\.phtml.*?&(amp;)?pre=(.*?)\".*?>(.*?)</a>",
            Pattern.CASE_INSENSITIVE);
    private static final Pattern BUDDY_DETAILS = Pattern.compile(
            "Priateľ v mobile.*?"
            + "<td.*?>(.*?)</td>.*?<td.*?>(.*?)</td>.*?"
            + "<td><div class=\"s9\">(.*?)</div></td>.*?<td.*?>(.*?)</td></tr>",
            Pattern.DOTALL | Pattern.CASE_INSENSITIVE);
    
    private static final String BUDDY_GENDER_MALE = "m";
    private static final String BUDDY_GENDER_FEMALE = "ž";
    private static final String BUDDY_AGE_UNDEFINED = "--";
    
    private static final Pattern BUDDY_STATUS_CHATTING = Pattern.compile(
            "<a href=\"http://pokecp\\.AZet\\.sk/indexx\\.phtml.*?&(amp;)?lok=(.*?)\">Pokec, (.*?)</a>",
            Pattern.CASE_INSENSITIVE);
    private static final String BUDDY_STATUS_ONLINE = "prihlásený";
    private static final DateFormat BUDDY_LAST_LOGIN =
            new SimpleDateFormat("dd. MM. yyyy HH:mm", Main.SLOVAK_LOCALE);

    public List<Buddy> parse(InputStream in) throws IOException {
        List<Buddy> buddies = new ArrayList<Buddy>();
        BufferedReader reader = new BufferedReader(new InputStreamReader(in,
                Main.getProperty("azetclient.azet.encoding")));
        PagesSaver saver = new PagesSaver("buddyList");
        
        String line;
        try {
            while ((line = reader.readLine()) != null) {
                saver.println(line);

                int index;
                while ((index = line.indexOf(BUDDY_BEGIN)) > -1) {
                    line = line.substring(index + 1);
                    Buddy buddy = new Buddy();
                    Matcher matcher;

                    matcher = BUDDY_NAME.matcher(line);
                    if (matcher.find()) {
                        try {
                            buddy.setId(Integer.parseInt(matcher.group(2).trim()));
                        } catch (NumberFormatException ex) {
                            logger.warn("Invalid buddy id: " + matcher.group(2).trim(), ex);
                        }
                        buddy.setName(matcher.group(3).trim());
                    } else {
                        logger.warn("No buddy name found");
                    }

                    matcher = BUDDY_DETAILS.matcher(line);
                    if (matcher.find()) {
                        String group;

                        group = matcher.group(1).trim();
                        if (BUDDY_GENDER_MALE.equals(group)) {
                            buddy.setGender(Buddy.Gender.MALE);
                        } else if (BUDDY_GENDER_FEMALE.equals(group)) {
                            buddy.setGender(Buddy.Gender.FEMALE);
                        } else {
                            logger.warn("Invalid buddy gender: " + group + "; buddy name: " + buddy.getName());
                        }

                        group = matcher.group(2).trim();
                        try {
                            if (BUDDY_AGE_UNDEFINED.equals(group)) {
                                buddy.setAge(-1);
                            } else {
                                buddy.setAge(Integer.parseInt(group));
                            }
                        } catch (NumberFormatException ex) {
                            logger.warn("Invalid buddy age: " + group + "; buddy name: " + buddy.getName(), ex);
                        }
                        
                        group = HtmlEntitiesConverter
                                .convert(matcher.group(3)).trim();
                        buddy.setLocation(group);
                        
                        group = matcher.group(4).trim();
                        if (BUDDY_STATUS_ONLINE.equals(group)) {
                            buddy.setStatus(Buddy.Status.ONLINE);
                        } else {
                            Matcher chattingMatcher =
                                    BUDDY_STATUS_CHATTING.matcher(group);
                            if (chattingMatcher.matches()) {
                                buddy.setStatus(Buddy.Status.CHATTING);
                                try {
                                    buddy.setRoomNo(Integer.parseInt(chattingMatcher.group(2)));
                                } catch (NumberFormatException ex) {
                                    logger.warn("Invalid buddy room no.: " + chattingMatcher.group(2)
                                            + "; buddy name: " + buddy.getName(), ex);
                                }
                                buddy.setRoom(chattingMatcher.group(3));
                            } else {
                                buddy.setStatus(Buddy.Status.OFFLINE);
                                try {
                                    buddy.setLastLogin(BUDDY_LAST_LOGIN.parse(group));
                                } catch (ParseException ex) {
                                    logger.warn("Invalid buddy last login: " + group
                                            + "; buddy name: " + buddy.getName(), ex);
                                }
                            }
                        }
                    } else {
                        logger.warn("No buddy details found; buddy name: " + buddy.getName());
                    }

                    buddies.add(buddy);
                }
            }
        } finally {
            saver.close();
            reader.close();
        }
        
        return buddies;
    }
    
}
